package com.iwhalecloud.bss.kite.cucc.order.accept.chain.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.iwhalecloud.bss.kite.common.constant.TableConsts;
import com.iwhalecloud.bss.kite.common.util.KiteObjectUtils;
import com.iwhalecloud.bss.kite.common.util.SeqUtils;
import com.iwhalecloud.bss.kite.cucc.order.accept.chain.AbstractOrderHandler;
import com.iwhalecloud.bss.kite.cucc.order.util.AcceptUtils;
import com.iwhalecloud.bss.kite.dataservice.entity.OrderItem;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferInst;
import com.iwhalecloud.bss.kite.dataservice.entity.order.OrderItemChange;
import com.iwhalecloud.bss.kite.dataservice.util.SplictUtil;
import com.iwhalecloud.bss.kite.order.client.dto.InstContainer;
import com.iwhalecloud.bss.kite.order.client.dto.OrderRequest;
import com.ztesoft.bss.base.staticdata.CoreDataRule;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 订单受理流程：订单分解
 */
@Component
public class OrderSplitHandler extends AbstractOrderHandler {

    @Override
    public void doHandle(OrderRequest request) {
        /*List<OrderItem> newOrderItems = Lists.newArrayList();
        Map<String, List<OrderItemChange>> newOrderItemChanges = Maps.newHashMap();
        String askFlow = ServiceOfferCache.get(request.getServiceOfferId()).getAskFlow();
        List<OrderItem> orderItems = OrderContainer.ofRequest(request).listOrderItems();
        for (OrderItem orderItem : orderItems) {
            // 计算订单项服务提供
            orderItem.setServiceOfferId(AcceptUtils.getServiceOfferId(request, orderItem));
            String offerType = orderItem.getOfferKind();
            String orderSource = orderItem.getOrderSource();
            String serviceOfferId = orderItem.getServiceOfferId();
            List<OrderItemChange> orderItemChanges = request.getOrderContainer().getOrderItemChangeMap()
                .get(orderItem.getOrderItemId());
            // 是否拆单
            if ((SplictUtil.isSplit(serviceOfferId, orderSource, offerType) || SplictUtil.isSplitByAskFlow(askFlow))
                && !CollectionUtils.isEmpty(orderItemChanges)) {
                // 订单变动分组
                Map<String, List<OrderItemChange>> orderItemChangeServMap = orderItemChangeGroupSplitByServ(request,
                    orderItem, orderItemChanges);

                // 订单合并
                Map<String, List<OrderItemChange>> mergeMap = orderItemChangeMergeByServ(orderItemChangeServMap);

                // 为每个订单变动分组生成一个新订单
                rebuildNewOrderItem(orderItem, newOrderItems, newOrderItemChanges, mergeMap);
            }
            else {
                newOrderItems.add(orderItem);
                newOrderItemChanges.put(orderItem.getOrderItemId(), orderItemChanges);
            }
        }

        // 重新设置订单项和变动信息
        request.getOrderContainer().getOrderItemMap().clear();
        newOrderItems.forEach(t -> OrderContainer.ofRequest(request).addOrderItem(t));
        request.getOrderContainer().setOrderItemChangeMap(newOrderItemChanges);*/
    }

    /**
     * 根据服务提供进行订单项拆分分组处理 <br>
     * key:serviceOfferId
     * @param request
     * @param orderItem
     * @param orderItemChanges
     * @return <br>
     */
    private Map<String, List<OrderItemChange>> orderItemChangeGroupSplitByServ(OrderRequest request,
        OrderItem orderItem, List<OrderItemChange> orderItemChanges) {
        Map<String, List<OrderItemChange>> orderItemChangeServMap = Maps.newHashMap();
        String orderSource = orderItem.getOrderSource();
        // 获取订单项主产品规格ID
        String prodId = AcceptUtils.getOrderItemProdId(request, orderItem);
        String actionType = CoreDataRule.RUL_C_0006_1200;
        String oldServiceOfferId = orderItem.getServiceOfferId();
        for (OrderItemChange orderItemChange : orderItemChanges) {
            String tableName = orderItemChange.getTableName();
            String fieldName = orderItemChange.getFieldName();
            String offerType = getOfferTypeOfOrderItemChange(request, orderItemChange);

            String servOfferId = SplictUtil.computeServiceOfferId(orderSource, tableName, fieldName, prodId, actionType,
                oldServiceOfferId, offerType);

            orderItemChangeServMap.computeIfAbsent(servOfferId, key -> new ArrayList<OrderItemChange>())
                .add(orderItemChange);
        }
        return orderItemChangeServMap;
    }

    /**
     * Description: <br>
     * 获取变动信息对应销售品类型
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @param request
     * @param orderItemChange
     * @return <br>
     */
    private String getOfferTypeOfOrderItemChange(OrderRequest request, OrderItemChange orderItemChange) {
        if (StringUtils.equalsIgnoreCase(orderItemChange.getTableName(), TableConsts.OfferInst.getTableName())) {
            OfferInst offerInst = InstContainer.ofRequest(request).getOfferInst(orderItemChange.getInstId());
            return Optional.ofNullable(offerInst).map(OfferInst::getOfferType).orElse("");
        }
        return "";
    }

    /**
     * Description: <br>
     * 根据服务提供进行订单项分组合并处理
     * @taskId <br>
     * @param orderItemChangeServMap
     * @return <br>
     */
    private Map<String, List<OrderItemChange>> orderItemChangeMergeByServ(
        Map<String, List<OrderItemChange>> orderItemChangeServMap) {
        Map<String, List<OrderItemChange>> mergeMap = Maps.newHashMap();

        if (MapUtils.isEmpty(orderItemChangeServMap) || orderItemChangeServMap.keySet().size() == 1) {
            return orderItemChangeServMap;
        }

        // 服务提供两两比较
        Map<String, List<String>> mergeServOfferIdMap = SplictUtil.mergeServOfferId(orderItemChangeServMap.keySet());
        if (MapUtils.isEmpty(mergeServOfferIdMap)) {
            return orderItemChangeServMap;
        }
        // 标记被合并过的服务提供
        Set<String> flagSet = Sets.newHashSet();
        for (Entry<String, List<OrderItemChange>> entry : orderItemChangeServMap.entrySet()) {
            if (flagSet.contains(entry.getKey())) {
                continue;
            }
            // 存在需要合并变动服务提供
            if (mergeServOfferIdMap.containsKey(entry.getKey())) {
                // 先把当前变动添加返回合并列表
                if (!mergeMap.containsKey(entry.getKey())) {
                    mergeMap.put(entry.getKey(), entry.getValue());
                }

                mergeServOfferIdMap.get(entry.getKey()).stream().forEach(toMergeServOfferId -> {
                    // 标记待合并服务提供
                    flagSet.add(toMergeServOfferId);
                    // 合并获取被合并变动信息
                    mergeMap.computeIfAbsent(entry.getKey(), key -> new ArrayList<OrderItemChange>())
                        .addAll(orderItemChangeServMap.get(toMergeServOfferId));
                });
            }
            else {
                boolean flag = mergeServOfferIdMap.values().stream().anyMatch(p -> p.contains(entry.getKey()));
                if (!flag) {
                    mergeMap.put(entry.getKey(), entry.getValue());
                }
            }
        }

        return mergeMap;
    }

    /**
     * Description: <br>
     * 重新生成新订单项和订单变动信息
     * @taskId <br>
     * @param orderItem
     * @param newOrderItems
     * @param newOrderItemChanges
     * @param chgGroupMap <br>
     */
    private void rebuildNewOrderItem(OrderItem orderItem, List<OrderItem> newOrderItems,
        Map<String, List<OrderItemChange>> newOrderItemChanges, Map<String, List<OrderItemChange>> chgGroupMap) {
        // 为每个订单变动分组生成一个新订单
        AtomicBoolean usedFlag = new AtomicBoolean();
        for (Entry<String, List<OrderItemChange>> chgEntry : chgGroupMap.entrySet()) {
            OrderItem newOrderItem = KiteObjectUtils.clone(orderItem);
            String newOrderItemId = orderItem.getOrderItemId();
            if (usedFlag.get()) {
                newOrderItemId = SeqUtils.genOrderItemId(orderItem.getAcceptLanId());
            }
            else {
                usedFlag.set(true);
            }
            newOrderItem.setOrderItemId(newOrderItemId);
            newOrderItem.setServiceOfferId(chgEntry.getKey());
            // 调整原变动信息里面订单项ID
            for (OrderItemChange chg : chgEntry.getValue()) {
                chg.setOrderItemId(newOrderItemId);
            }
            newOrderItems.add(newOrderItem);
            newOrderItemChanges.computeIfAbsent(newOrderItemId, key -> Lists.newArrayList())
                .addAll(chgEntry.getValue());
        }
    }
}
